1 /* FOREGEJ - FOrmatting REfactoring GEnerating Java
2 *
3 * Copyright (C) 2003 Andreas Arrgard
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 package com.octagroup.foregej.antlr;
20 import antlr.CommonASTWithHiddenTokens;
21 import antlr.collections.AST;
22 import java.util.List;
23 /***
24 * The base representation of an AST in the FOREGEJ system.
25 */
26 public class BaseAST extends CommonASTWithHiddenTokens
27 {
28 public static int WRAP_PREF_NONE=0;
29 public static int WRAP_PREF_NO=1;
30 public static int WRAP_PREF_OK=2;
31 /***
32 * This is the parent AST.
33 */
34 private AST _parent;
35 /***
36 * the AST factory that created this token
37 */
38 protected DynASTFactory astFactory_;
39 /***
40 * Constructor creates a new BaseAST object.
41 */
42 public BaseAST()
43 {
44 }
45 /***
46 * Constructor creates a new BaseAST object.
47 *
48 * @param ast DOCUMENT ME!
49 */
50 public BaseAST(AST ast)
51 {
52 this.setType(ast.getType());
53 this.setText(ast.getText());
54 this.setFirstChild(ast.getFirstChild());
55 this.setNextSibling(ast.getNextSibling());
56 }
57 /***
58 * As we invoke the <code>NodeWriter.write</code>we store how the node
59 * prefers to handle wrapping.
60 *
61 * @return the wrapping preference.
62 */
63 public int getWrappingPreference()
64 {
65 return WRAP_PREF_NONE;
66 }
67 /***
68 * DOCUMENT ME!
69 *
70 * @param type DOCUMENT ME!
71 * @return DOCUMENT ME!
72 */
73 public AST getChildAST(Class type)
74 {
75 List asts=getChildASTs(type);
76 if(asts==null) {
77 return null;
78 }
79 if(asts.size()==0) {
80 return null;
81 }
82 return (AST)asts.get(0);
83 }
84 /***
85 * Returns all the child asts that match the supplied type.
86 *
87 * @param type the type to look for.
88 * @return
89 */
90 public List getChildASTs(Class type)
91 {
92 return new AST_List(this, type);
93 }
94 /***
95 * Returns all the child asts that do not match the supplied classes.
96 *
97 * @param excluding the classes to exclude.
98 * @return all the child asts that do not match the supplied classes.
99 */
100 public List getChildASTsExcluding(Class[] excluding)
101 {
102 return new AST_List(this, null, excluding);
103 }
104 /***
105 * Helper method that inserts an ast after the last occurence of the
106 * supplied type.
107 *
108 * @param afterType DOCUMENT ME!
109 * @param newAst the new ast
110 * @throws RuntimeException DOCUMENT ME!
111 */
112 public void insertAfter(Class afterType,AST newAst)
113 {
114 AST_ListIterator iter=new AST_ListIterator(this, afterType);
115 AST node=null;
116 while(iter.hasNext()){
117 node=(AST)iter.next();
118 }
119 if(node==null) {
120 throw new RuntimeException("Failed to insert AST after node of type("+afterType.getName()+"):"+this);
121 }
122 newAst.setNextSibling(node.getNextSibling());
123 node.setNextSibling(newAst);
124 }
125 /***
126 * Helper method that replaces a child or ast with a new ast.
127 *
128 * @param newAst the new ast
129 */
130 public void insertFirst(AST newAst)
131 {
132 AST nextSibling=getFirstChild();
133 setFirstChild(null);
134 newAst.setNextSibling(nextSibling);
135 setFirstChild(newAst);
136 }
137 /***
138 * Helper method that replaces a child or ast with a new ast.
139 *
140 * @param oldAst the ast to replace
141 * @param newAst the new ast
142 * @return
143 */
144 public boolean replaceAST(AST oldAst,AST newAst)
145 {
146 // we cannot replace a null node
147 if(oldAst==null) {
148 return false;
149 }
150 // start with the first child and compare
151 AST node=getFirstChild();
152 if(node==oldAst) {
153 AST nextSibling=node.getNextSibling();
154 node.setNextSibling(null);
155 newAst.setNextSibling(nextSibling);
156 setFirstChild(newAst);
157 }
158 while(node!=null){
159 if(node.getNextSibling()==oldAst) {
160 AST nextSibling=node.getNextSibling().getNextSibling();
161 node.getNextSibling().setNextSibling(null);
162 newAst.setNextSibling(nextSibling);
163 node.setNextSibling(newAst);
164 return true;
165 }
166 node=node.getNextSibling();
167 }
168 throw new RuntimeException("Failed to replace AST!");
169 }
170 /***
171 * DOCUMENT ME!
172 *
173 * @param nw DOCUMENT ME!
174 * @throws RuntimeException DOCUMENT ME!
175 */
176 public void write(NodeWriter nw)
177 {
178 throw new RuntimeException("Cannot write a:"+getType()+"["+getClass().getName()+"]");
179 }
180 /***
181 * Compares two objects
182 *
183 * @param o1
184 * @param o2
185 * @return
186 */
187 public boolean equals(Object o1,Object o2)
188 {
189 if(o1==o2) return true;
190 if(o1==null) return false;
191 return o1.equals(o2);
192 }
193 /***
194 * Performs a deep copy of the node.
195 *
196 * @return
197 */
198 public BaseAST deepCopy()
199 {
200 return (BaseAST)deepCopy(this);
201 }
202 /***
203 * @param ast
204 * @return
205 */
206 public static AST deepCopy(AST ast)
207 {
208 try{
209 AST copy=(AST)ast.getClass().newInstance();
210 copy.initialize(ast);
211 if(ast instanceof BaseAST) {
212 ((BaseAST)copy).hiddenBefore=((BaseAST)ast).hiddenBefore;
213 ((BaseAST)copy).hiddenAfter=((BaseAST)ast).hiddenAfter;
214 }
215 AST node=ast.getFirstChild();
216 if(node!=null) {
217 copy.setFirstChild(deepCopy(node));
218 node=node.getNextSibling();
219 }
220 AST siblingOwner=copy.getFirstChild();
221 while(node!=null){
222 siblingOwner.setNextSibling(deepCopy(node));
223 siblingOwner=siblingOwner.getNextSibling();
224 node=node.getNextSibling();
225 }
226 return copy;
227 }catch (InstantiationException e) {
228 throw new IllegalStateException("Failed to copy node:InstantiationException:"+e.getMessage());
229 }catch (IllegalAccessException e) {
230 throw new IllegalStateException("Failed to copy node:InstantiationException:"+e.getMessage());
231 }
232 }
233 /***
234 * @param includeComments
235 * @return
236 */
237 public String toString(boolean includeComments)
238 {
239 NodeWriter nw=new NodeWriter();
240 nw.write(this);
241 return nw.toString();
242 }
243 /***
244 * @return
245 */
246 public String toString()
247 {
248 return toString(true);
249 }
250 /***
251 * @param o
252 * @return
253 */
254 public boolean equals(Object o)
255 {
256 if(o==null) return false;
257 if(o.getClass()!=getClass()) return false;
258 BaseAST a=(BaseAST)o;
259 if(false==equals(getText(), a.getText())) return false;
260 AST thisNode=getFirstChild();
261 AST aNode=a.getFirstChild();
262 while(thisNode!=null&&aNode!=null){
263 if(false==equals(thisNode, aNode)) return false;
264 thisNode=thisNode.getNextSibling();
265 aNode=aNode.getNextSibling();
266 }
267 return thisNode==null&&aNode==null;
268 }
269 /***
270 * Sets the token hidden before this ast.
271 *
272 * @param hiddenBefore
273 */
274 public void setHiddenBefore(BaseToken hiddenBefore)
275 {
276 this.hiddenBefore=hiddenBefore;
277 if(hiddenBefore!=null) {
278 ((BaseToken)hiddenBefore).setHiddenAfter(null);
279 }
280 }
281 /***
282 * Sets the token hidden after this ast.
283 *
284 * @param hiddenAfter
285 */
286 public void setHiddenAfter(BaseToken hiddenAfter)
287 {
288 this.hiddenAfter=hiddenAfter;
289 if(hiddenAfter!=null) {
290 ((BaseToken)hiddenAfter).setHiddenBefore(null);
291 }
292 }
293 /***
294 * Sets the factory used to create this AST.
295 * <p>
296 * This method is invoked from the AST factory when the token is
297 * created.
298 * </p>
299 *
300 * <p>
301 * The factory is used to signal that types have been changed.
302 * </p>
303 *
304 * @param factory the factory that created the AST
305 */
306 public void setASTFactory(DynASTFactory factory)
307 {
308 astFactory_=factory;
309 }
310 /***
311 * Sets the type of this ast.
312 * <p>
313 * It also signals to the AST factory that we have modified the type
314 * so that the next call to the DynASTFactory scans the tree to
315 * replace the created AST with the new type.
316 * </p>
317 *
318 * @param type
319 */
320 public void setType(int type)
321 {
322 int oldType=getType();
323 super.setType(type);
324 //
325 // If the AST is uninitialized we do not signal the change.
326 // The token types spec. starts at 1.
327 //
328 if(oldType!=0&&oldType!=type) astFactory_.typeAltered(this);
329 }
330 /***
331 * Sets the parent AST.
332 *
333 * @param parent the parent AST
334 */
335 public void setParentAst(AST parent)
336 {
337 _parent=parent;
338 }
339 /***
340 * Returns the parent AST.
341 *
342 * @return the parent AST.
343 */
344 public AST getParentAst()
345 {
346 return _parent;
347 }
348 /***
349 * As we set the first child we update the parent of the child ast to
350 * this ast.
351 * <p>
352 * We need to update all the siblings of the first child as well.
353 * </p>
354 *
355 * @param child
356 */
357 public void setFirstChild(AST child)
358 {
359 //
360 // TODO: Rewrite the AST_List so that we do not need to check if the parents are same.
361 //
362 if(child!=null&&((BaseAST)child).getParentAst()!=null&&
363 ((BaseAST)child).getParentAst()!=this) {
364 throw new IllegalArgumentException("Cannot add a child that has a parent reference other than this one.");
365 }
366 setFirstChildForced(child);
367 }
368 /***
369 * As we set the first child we update the parent of the child ast to
370 * this ast.
371 * <p>
372 * We need to update all the siblings of the first child as well.
373 * </p>
374 *
375 * <p>
376 * This method does not check that the new child has a parent
377 * specified.
378 * </p>
379 *
380 * @param child
381 */
382 public void setFirstChildForced(AST child)
383 {
384 //System.out.println(">setFirstChildForced");
385 //
386 // none of the current childs reference this parent
387 // anymore
388 //
389 updateParentOfChilds(null);
390 super.setFirstChild(child);
391 //
392 // update parents of all the new childs
393 //
394 updateParentOfChilds(this);
395 //System.out.println("<setFirstChildForced");
396 }
397 /***
398 * Helper method that updates the parent of all the children to the
399 * supplied parent.
400 * <p>
401 * This method is invoked from the setFirstChild method to update the
402 * parent references of all the children
403 * </p>
404 *
405 * @param parent
406 */
407 private void updateParentOfChilds(AST parent)
408 {
409 BaseAST node=(BaseAST)getFirstChild();
410 while(node!=null&&node.getParentAst()!=parent){
411 node.setParentAst(parent);
412 node=(BaseAST)node.getNextSibling();
413 }
414 }
415 /***
416 * As we set the next sibling we update the parent ast to the same ast
417 * as this node.
418 *
419 * @param sib
420 */
421 public void setNextSibling(AST sib)
422 {
423 //
424 // TODO: Rewrite the AST_List so that we do not need to check if the parents are same.
425 //
426 if(sib!=null&&((BaseAST)sib).getParentAst()!=null&&
427 ((BaseAST)sib).getParentAst()!=getParentAst()) {
428 throw new IllegalArgumentException("Cannot add a child that has a parent reference other than the parent of this AST.");
429 }
430 setNextSiblingForced(sib);
431 }
432 /***
433 * As we set the next sibling we update the parent ast to the same ast
434 * as this node.
435 * <p>
436 * This method does not check that the supplied sibling has a parent
437 * AST specified.
438 * </p>
439 *
440 * @param sib
441 */
442 public void setNextSiblingForced(AST sib)
443 {
444 //System.out.println(">setNextSiblingForced");
445 //
446 // if this ast already have a sibling - remove it and all of its successors
447 //
448 BaseAST previousSib=(BaseAST)getNextSibling();
449 while(previousSib!=null&&previousSib.getParentAst()!=null){
450 previousSib.setParentAst(null);
451 previousSib=(BaseAST)previousSib.getNextSibling();
452 }
453 super.setNextSibling(sib);
454 //
455 // set the parent of the added sibling
456 //
457 while(sib!=null&&((BaseAST)sib).getParentAst()!=getParentAst()){
458 ((BaseAST)sib).setParentAst(getParentAst());
459 sib=sib.getNextSibling();
460 }
461 }
462 }
This page was automatically generated by Maven